from collections import namedtuple
from flask_httpauth import HTTPBasicAuth
from itsdangerous import JSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired
from flask import current_app, g, request
from app.libs.error_code import AuthFailed, Forbidden
from app.libs.scope import is_in_scope

User = namedtuple('User', ['uid', 'ac_type', 'scope'])
auth = HTTPBasicAuth()


@auth.verify_password
def verify_token(token, null):
    ''' HTTP有自身的发送账号密码方式
        把参数放到header中比如:Authorization=basic base64(account: password)
        借助这种形式,可以把账号密码替换成token,完成状态的保持 '''
    user_info = check_token(token)
    if not user_info:
        return False
    else:
        g.user = user_info
        return True


def check_token(token):
    s = Serializer(current_app.config['SECRET_KEY'])
    try:
        token_dict = s.loads(token)
    except BadSignature:
        raise AuthFailed(msg='token error')
    except SignatureExpired:
        raise AuthFailed(msg='token expired')

    uid = token_dict['uid']
    ac_type = token_dict['ac_type']
    scope = token_dict['scope']
    if not is_in_scope(scope, request.endpoint):
        raise Forbidden()
    # TODO 这里为什么要返回一个元祖对象呢?好处是什么呢?
    # 用起来比较爽,可以user.user_info写起来可读性高,代码看起来比较高级
    return User(uid, ac_type, scope)


# @file_api.route('/download')
# def file_download():
#     filename = request.args.get('filename')
#     if filename is None:
#         return ParameterError(msg='参数未传')
#
#     file_path = ZIP_PATH + filename
#     file_list = os.listdir(file_path)
#     if file_list is None:
#         return NotFound()
#
#     paths = os.listdir(ZIP_PATH)
#     if 'file.zip' in paths:
#         os.remove(ZIP_PATH + 'file.zip')
#
#     with zipfile.ZipFile(ZIP_PATH + 'file.zip', "w", zipfile.ZIP_DEFLATED) as zf:
#         for _file in file_list:
#             name = file_path + '/' + _file
#             zf.write(name)
#
#     return send_from_directory(ZIP_PATH, 'file.zip', as_attachment=True)
